// Copyright 2022 a.o.smith ALL Rights Reserved
package com.liuxinlong.modules.material.service.impl;

import com.liuxinlong.common.ExcelImportCallBack;
import com.liuxinlong.common.ExcelImportService;
import com.liuxinlong.common.ImportResp;
import com.liuxinlong.common.RowError;
import com.liuxinlong.common.SnowFlake;
import com.liuxinlong.common.uploadSMBJ.SMBJConfig;
import com.liuxinlong.common.uploadSMBJ.SMBJInterface;
import com.liuxinlong.modules.dao.MaterialDao;
import com.liuxinlong.modules.dao.ShareFileDao;
import com.liuxinlong.modules.entity.Material;
import com.liuxinlong.modules.entity.ShareFile;
import com.liuxinlong.modules.material.dto.MaterialInfoDto;
import com.liuxinlong.modules.material.service.MaterialService;
import com.liuxinlong.modules.sync.service.SyncService;
import com.liuxinlong.utils.ObjectUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 物料管理service实现
 *
 * @author liuxinlong@hotwater.com.cn
 * @version 1.0.0
 * @since 2022年2月17日
 */
@Service
@Slf4j
public class MaterialServiceImpl implements MaterialService {

    @Autowired
    private MaterialDao materialDao;

    @Autowired
    private ExcelImportService excelImportService;

    @Autowired
    private SMBJInterface smbjInterface;

    @Autowired
    private SMBJConfig smbjConfig;

    @Autowired
    private ShareFileDao shareFileDao;

    @Autowired
    private SyncService syncService;

    @Override
    public List<Map<String, Object>> pageMaterialList(Map<String, Object> queryParam) {
        List<Material> originList = materialDao.pageMaterialList(queryParam);
        List<Map<String, Object>> resultList = new ArrayList<>(originList.size());
        int sort = (int) queryParam.get("startNum") + 1;
        for (Material material : originList) {
            Map<String, Object> map = ObjectUtils.object2Map(material);
            map.put("sort", sort);
            resultList.add(map);
            sort++;
        }
        return resultList;
    }

    @Override
    public int getMaterialCount(Map<String, Object> queryParam) {

        return materialDao.getMaterialCount(queryParam);
    }

    @Override
    public void addMaterial(Material material) {
        material.setId(SnowFlake.nextIdStr());
        materialDao.addMaterial(material);
    }

    @Override
    public void updateMaterial(Material material) {
        materialDao.updateMaterial(material);
    }

    @Override
    public void deleteMaterial(String id) {
        materialDao.deleteMaterial(id);
    }

    @Override
//	@Async
    public int syncDrawFile() {
        List<ShareFile> drawFileList = smbjInterface.connectDraw(smbjConfig.getDrawHost());
        List<ShareFile> allShareFile = new ArrayList<>();
        allShareFile.addAll(drawFileList);
        Map<String, Map<String, String>> existFileMap = shareFileDao.getAllFileMap(2);
        List<ShareFile> addFileList = new ArrayList<>();
        for (ShareFile shareFile : allShareFile) {
            if (existFileMap.containsKey(shareFile.getSourceNo() + shareFile.getFileName())) {
                continue;
            }
            shareFile.setId(SnowFlake.nextIdStr());
            addFileList.add(shareFile);
        }
        if (addFileList.isEmpty()) {
            return 0;
        }
        shareFileDao.insertBatch(addFileList);
        return addFileList.size();
    }

    @Override
    public ImportResp importMaterials(String fileName) {
        String filePath = fileName;
        return excelImportService.excelFile(filePath, 2, new ExcelImportCallBack() {
            @Override
            public Collection<RowError> checkRow(String[] record) {
                return checkRecordValid(record);
            }

            @Override
            public boolean persistRowToDb(String[] record) {
                MaterialInfoDto materialInfo = covertToBean(record);
                return false;
//				try {
//					materialReplaceDao.insert(mocDetail);
//					return true;
//				} catch (Exception e) {
//					return false;
//				}
            }

            @Override
            public ImportResp partFailure(ImportResp resp) {
                resp.setRetMessage("导入物料数据部分失败，总数=" + resp.getTotal() + ",失败总数=" + resp.getFailedTotal());
                return resp;
            }

            @Override
            public ImportResp allSuccess(ImportResp resp) {
                resp.setRetMessage("导入物料数据全部成功，总数=" + resp.getTotal());
                return resp;
            }

            @Override
            public List<Map> convertFailList(List<String[]> failRecords) {
                List<Map> list = new ArrayList<>();
                int sort = 1;
                for (String[] failRecord : failRecords) {
                    Map item = new HashMap();
                    item.put("sort", sort);
                    item.put("materialNo", failRecord[1].trim());
                    item.put("name", failRecord[2].trim());
                    item.put("name2", failRecord[3].trim());
                    item.put("childMaterial", failRecord[4].trim());
                    item.put("pmCode", failRecord[5]);
                    item.put("region", failRecord[6]);
                    list.add(item);
                    sort++;
                }
                return list;
            }

        });
    }

    @Override
    public ImportResp batchAddMaterial(List<MaterialInfoDto> dataList) {
        return null;
    }


    /**
     * 转换数据为入库数据
     *
     * @param record 数据记录
     * @return 入库数据
     */
    private MaterialInfoDto covertToBean(String[] record) {
        MaterialInfoDto materialInfo = new MaterialInfoDto();
        materialInfo.setMaterialNo(record[1].trim());
        materialInfo.setDescOne(record[2].trim());
        materialInfo.setDescTwo(record[3].trim());
        materialInfo.setChildMaterial(record[4].trim());
        materialInfo.setPmCode(record[5].trim());
        materialInfo.setRegion(record[6].trim());
        return materialInfo;

    }

    /**
     * 校验参数合法性
     *
     * @param record 导入数据
     * @return 参数合法性
     */
    private Collection<RowError> checkRecordValid(String[] record) {
        List<RowError> rowErrors = new ArrayList<>();
        if (StringUtils.isEmpty(record[1].trim())) {
            addRowError("物料号不能为空", rowErrors);
        } else {
            if (record[1].trim().length() > 20) {
                addRowError("物料号长度不能超过20", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[2].trim())) {
            addRowError("物料描述不能为空", rowErrors);
        } else {
            if (record[2].trim().length() > 500) {
                addRowError("物料描述长度不能超过500", rowErrors);
            }
        }
//		if (StringUtils.isEmpty(record[3].trim())) {
//			addRowError("兼容性不能为空", rowErrors);
//		} else {
//			String com = record[3].trim();
//			if (!StringUtils.equals(com, "是") && !StringUtils.equals(com, "否")) {
//				addRowError("兼容性字段非法", rowErrors);
//			}
//		}
//		if (StringUtils.isEmpty(record[4].trim())) {
//			addRowError("ECN号不能为空", rowErrors);
//		} else {
//			if (record[4].trim().length() > 20) {
//				addRowError("ECN号长度不能超过20", rowErrors);
//			}
//		}

        return rowErrors;
    }

    /**
     * 添加错误行数据
     *
     * @param errorMessage 错误信息
     * @param rowErrors    错误行数据
     */
    private void addRowError(String errorMessage, List<RowError> rowErrors) {
        RowError rowError = new RowError(errorMessage);
        rowErrors.add(rowError);
    }

    /**
     * 获取父项
     *
     * @param currentMaterial 当前物料号
     * @param region          所属域
     * @param materialList    父项物料号列表
     * @return 父项物料号列表
     */
    private List<String> getParentMaterial(List<String> currentMaterial, String region, List<String> materialList) {
        if (currentMaterial.isEmpty()) {
            return new ArrayList<>();
        }
        int total = currentMaterial.size();
        List<MaterialInfoDto> materialInfoDtoList = new ArrayList<>();
        if (total > 100) {
            int maxInt = (int) Math.ceil(total / 100);
            for (int i = 0; i < maxInt; i++) {
                int startNum = 100 * i;
                List<String> subList = currentMaterial.subList(startNum, Math.min(startNum + 100, total - 1));
                List<MaterialInfoDto> subMaterialInfoDtoList = syncService.getParentMaterials(subList, region);
                if (!ObjectUtils.isEmpty(subMaterialInfoDtoList)) {
                    materialInfoDtoList.addAll(subMaterialInfoDtoList);
                }
            }
        } else {
            materialInfoDtoList = syncService.getParentMaterials(currentMaterial, region);
        }
        if (materialInfoDtoList.size() > 0) {
            List<String> currents = new ArrayList<>();
            for (MaterialInfoDto materialInfoDto : materialInfoDtoList) {
                if (StringUtils.isEmpty(materialInfoDto.getMaterialNo())) {
                    materialList.add(materialInfoDto.getChildMaterial());
                    continue;
                }
                currents.add(materialInfoDto.getMaterialNo());
            }
//			materialList.addAll(currents);
            materialList = getParentMaterial(currents, region, materialList);
        }
        return materialList;
    }

    /**
     * 获取最终父项
     *
     * @param material 当前物料号
     * @param region   所属域
     * @return 父项物料号列表
     */
    @Override
    public List<Map<String, Object>> getFinalParentMaterial(String material, String region) {
        List<String> materialList = new ArrayList<>();
        List<String> currentMaterial = new ArrayList<>();
        currentMaterial.add(material);
        List<String> finalParentList = getParentMaterial(currentMaterial, region, materialList);
        List<Map<String, Object>> materialInfoDtoList = new ArrayList<>();
        for (String materialId : finalParentList) {
            MaterialInfoDto dto = new MaterialInfoDto();
            dto.setMaterialNo(materialId);
            Map<String, Object> materialMap = ObjectUtils.object2Map(dto);
            materialInfoDtoList.add(materialMap);
        }
        return materialInfoDtoList;
    }

    @Override
    public Map<String, Object> getMaterialExpand(String material, String region) {
        Map<String,Object> dataMap = syncService.getMaterialExpInfo(material,region);
        return dataMap;
    }
}
